use nom::{IResult, branch::alt};

use super::{var::VarStatement, Help};
use super::action::{
    BackupStatement,
    RestoreStatement,
    VersionStatement,
};

pub trait Parse<'a> where Self:Sized {
    fn parse(raw_str:&'a str) -> IResult<&'a str,Self>;
}


#[derive(Debug)]
pub enum Statement<'a> {
    Var(VarStatement<'a>),
    Backup(BackupStatement<'a>),
    Restore(RestoreStatement<'a>),
    Version(VersionStatement<'a>),
    Help(Help<'a>),
    Notes,
}

impl<'a> Statement<'a> {
    pub fn is_notes(&self) -> bool {
        if let Self::Notes = self {
            true
        } else {
            false
        }
    }
}

impl<'a> Parse<'a> for Statement<'a> {
    fn parse(raw_str:&'a str) -> IResult<&'a str,Self> {
        let raw_str = raw_str.trim_start();
        if raw_str.starts_with("//") || raw_str.starts_with("#") || raw_str.trim_start() == "" {
            return if let Some((_,raw_str)) = raw_str.split_once("\n") {
                Ok((raw_str,Self::Notes))
            } else {
                Ok((&raw_str[0..0],Self::Notes))
            };
        } else {
            alt((
                |raw_str|VarStatement::parse(raw_str).map(|(raw_str,var_statement)|(raw_str,Statement::Var(var_statement))),
                |raw_str|BackupStatement::parse(raw_str).map(|(raw_str,backup_statement)|(raw_str,Statement::Backup(backup_statement))),
                |raw_str|RestoreStatement::parse(raw_str).map(|(raw_str,restore_statement)|(raw_str,Statement::Restore(restore_statement))),
                |raw_str|VersionStatement::parse(raw_str).map(|(raw_str,version_statement)|(raw_str,Statement::Version(version_statement))),
                |raw_str|Help::parse(raw_str).map(|(raw_str,help_statement)|(raw_str,Statement::Help(help_statement))),
            ))(raw_str)
        }
    }
}

